﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PACKETPARSERMAX20.CORE.UPDATEFIELDS;

namespace PACKETPARSERMAX20.CORE
{
    public class WoWObjectUnit : WoWObjectBase
    {
        public WoWObjectUnit(WoWCore sender, UInt64 guid, TypeID pTypeID)
            : base(sender, guid, pTypeID)
        {
            FactionInfoList = new SortedList<int, FactionInfo>();
            AuraSpellIdList = new List<uint>();
        }

        public UInt32 Rank { get; set; }
        public UInt32 Family { get; set; }
        public UInt32 Class { get; set; }
        public string BgRealm { get; set; }
        public UInt32 Race { get; set; }
        public UInt32 Gender { get; set; }
        public UInt32 Level { get; set; }

        public SortedList<int, FactionInfo> FactionInfoList { get; set; }
        public List<uint> AuraSpellIdList { get; set; }

        private creature_template_addon _creature_template_addon = null;
        private creature_equip_template _creature_equip_template = null;
        private creature_addon _creature_addon = null;
        private creature_involvedrelation _creature_involvedrelation = null;


        ~WoWObjectUnit()
        {
            if (_creature_template_addon != null)
            {
                GlobalCache.AddCreatureTemplateAddonSum(_creature_template_addon, Sender.ClientBuild);
            }

            if (_creature_equip_template != null)
            {
                GlobalCache.AddCreatureEquipTemplateSum(_creature_equip_template, Sender.ClientBuild);
            }


        }

        public override string Name
        {
            get
            {
                if (base.Name == null)
                {
                    if (Fields == null) { return base.Name; }
                    base.Name = GlobalCache.GetCreatureName(ENTRY);
                }

                return base.Name;
            }

            internal set
            {
                base.Name = value;
            }
        }

        #region Reaction

        public object lockobj = new object();

        public ObjectReaction GetObjectReactionToPlayer()
        {
            ObjectReaction reaction = ObjectReaction.NONE;



            if ((TypeID == TypeID.TYPEID_PLAYER || TypeID == TypeID.TYPEID_UNIT) && this != Sender.Player)
            {
                var player = Sender.Player.UNIT_FIELD_FACTIONTEMPLATE;
                var target = UNIT_FIELD_FACTIONTEMPLATE;

                if (player != 0 && target != 0)
                {
                    var playerfactiontemplate = Sender.FactionHandler.GetFactionTemplate(player);
                    var targetfactiontemplate = Sender.FactionHandler.GetFactionTemplate(target);

                    var playerfaction = Sender.FactionHandler.GetFaction(playerfactiontemplate.faction);
                    var targetfaction = Sender.FactionHandler.GetFaction(targetfactiontemplate.faction);

                    if (this.TypeID != TypeID.TYPEID_PLAYER && targetfaction != null && targetfaction.reputationListID != -1)
                    {

                        int standing = Sender.Player.FactionInfoList[targetfaction.reputationListID].standing;
                        var reputationrank = ReputationToRank(standing);

                        switch (reputationrank)
                        {
                            case ReputationRank.REP_EXALTED:
                            case ReputationRank.REP_FRIENDLY:
                            case ReputationRank.REP_HONORED:
                            case ReputationRank.REP_REVERED:
                                {
                                    reaction = ObjectReaction.UNIT_FREINDLY;
                                } break;
                            case ReputationRank.REP_NEUTRAL:
                                {
                                    reaction = ObjectReaction.UNIT_NEUTRAL;
                                } break;
                            case ReputationRank.REP_UNFRIENDLY:
                                {
                                    reaction = ObjectReaction.UNIT_UNFREINDLY;
                                } break;
                            case ReputationRank.REP_HOSTILE:
                            case ReputationRank.REP_HATED:
                                {
                                    reaction = ObjectReaction.UNIT_AGGRESSIVE;
                                } break;
                        }


                    }

                    if (this.TypeID == TypeID.TYPEID_PLAYER && (UNIT_FIELD_FLAGS & (uint)UnitFlags.UNIT_FLAG_PVP) > 0)
                    {
                        reaction = ObjectReaction.PLAYER_ENEMY_FLAGED;
                    }
                    else
                    {
                        bool ishostiletarget = playerfactiontemplate.IsHostileTo(targetfactiontemplate);

                        if (this.TypeID == TypeID.TYPEID_PLAYER)
                        {
                            if (ishostiletarget)
                            {
                                reaction = ObjectReaction.PLAYER_ENEMY_UNFLAGED;
                            }
                            else
                            {
                                reaction = ObjectReaction.PLAYER_FREINDLY;
                            }
                        }
                        else
                        {
                            if (ishostiletarget)
                            {
                                reaction = ObjectReaction.UNIT_AGGRESSIVE;
                            }
                            else
                            {
                                reaction = ObjectReaction.UNIT_FREINDLY;
                            }
                        }

                    }

                }
            }
 

            return reaction;
        }
        public const int Reputation_Cap = 42999;
        public const int Reputation_Bottom = -42000;
        public int[] ReputationRank_Length = new int[] { 36000, 3000, 3000, 3000, 6000, 12000, 21000, 1000 };
        public ReputationRank ReputationToRank(int standing)
        {
            int Limit = Reputation_Cap + 1;
            for (int i = 8 - 1; i >= 8; --i)
            {
                Limit -= ReputationRank_Length[i];
                if (standing >= Limit)
                    return (ReputationRank)i;
            }
            return 0;
        }

        #endregion

        public int UNIT_FIELD_FACTIONTEMPLATE
        {
            get
            {
                if (TypeID == TypeID.TYPEID_PLAYER || TypeID == TypeID.TYPEID_UNIT)
                    return (int)GetUpdateValue("UNIT_FIELD_FACTIONTEMPLATE", typeof(int));
                return 0;
            }
        }

        public int UNIT_FIELD_LEVEL
        {
            get
            {
                if (TypeID == TypeID.TYPEID_PLAYER || TypeID == TypeID.TYPEID_UNIT)
                    return (int)GetUpdateValue("UNIT_FIELD_LEVEL", typeof(int));
                return 0;
            }
        }

        public uint UNIT_FIELD_FLAGS
        {
            get
            {
                if (TypeID == TypeID.TYPEID_PLAYER || TypeID == TypeID.TYPEID_UNIT)
                    return (uint)GetUpdateValue("UNIT_FIELD_FLAGS", typeof(uint));
                return 0;
            }
        }

        public uint UNIT_FIELD_FLAGS_2
        {
            get
            {
                if (TypeID == TypeID.TYPEID_PLAYER || TypeID == TypeID.TYPEID_UNIT)
                    return (uint)GetUpdateValue("UNIT_FIELD_FLAGS_2", typeof(uint));
                return 0;
            }
        }

        public uint UNIT_DYNAMIC_FLAGS
        {
            get
            {
                if (TypeID == TypeID.TYPEID_PLAYER || TypeID == TypeID.TYPEID_UNIT)
                    return (uint)GetUpdateValue("UNIT_DYNAMIC_FLAGS", typeof(uint));
                return 0;
            }
        }

        public uint UNIT_NPC_FLAGS
        {
            get
            {
                if (TypeID == TypeID.TYPEID_PLAYER || TypeID == TypeID.TYPEID_UNIT)
                    return (uint)GetUpdateValue("UNIT_NPC_FLAGS", typeof(uint));
                return 0;
            }
        }

        //public uint UNIT_FIELD_HEALTH
        //{
        //    get
        //    {
        //        if (typeid == TypeID.TYPEID_PLAYER || typeid == TypeID.TYPEID_UNIT)
        //            return (uint)GetUpdateValue("UNIT_FIELD_HEALTH", typeof(uint));
        //        return 0;
        //    }
        //}

        byte getRace() { return ((byte[])GetUpdateValue("UNIT_FIELD_BYTES_0", typeof(byte[])))[0]; }
        UInt32 getRaceMask() { return ((uint)(1 << (getRace() - 1))); }
        byte getClass() { return ((byte[])GetUpdateValue("UNIT_FIELD_BYTES_0", typeof(byte[])))[1]; }
        UInt32 getClassMask() { return ((uint)1 << (getClass() - 1)); }
        byte getGender() { return ((byte[])GetUpdateValue("UNIT_FIELD_BYTES_0", typeof(byte[])))[2]; }

        //public uint UNIT_VIRTUAL_ITEM_SLOT_ID
        //{
        //    get
        //    {
        //        if (typeid == TypeID.TYPEID_PLAYER || typeid == TypeID.TYPEID_UNIT)
        //            return (uint)GetUpdateValue("UNIT_VIRTUAL_ITEM_SLOT_ID", typeof(uint));
        //        return 0;
        //    }
        //}

        //public uint UNIT_VIRTUAL_ITEM_SLOT_ID_1
        //{
        //    get
        //    {
        //        if (typeid == TypeID.TYPEID_PLAYER || typeid == TypeID.TYPEID_UNIT)
        //            return (uint)GetUpdateValue("UNIT_VIRTUAL_ITEM_SLOT_ID_1", typeof(uint));
        //        return 0;
        //    }
        //}


        //public uint UNIT_VIRTUAL_ITEM_SLOT_ID_2
        //{
        //    get
        //    {
        //        if (typeid == TypeID.TYPEID_PLAYER || typeid == TypeID.TYPEID_UNIT)
        //            return (uint)GetUpdateValue("UNIT_VIRTUAL_ITEM_SLOT_ID_2", typeof(uint));
        //        return 0;
        //    }
        //}


        public void UpdateCreatureEquipTemplate()
        {
            var _UNIT_VIRTUAL_ITEM_SLOT_ID = GetEnumByName("UNIT_VIRTUAL_ITEM_SLOT_ID");
            if (_UNIT_VIRTUAL_ITEM_SLOT_ID == null) return;

            var _UNIT_VIRTUAL_ITEM_SLOT_ID_0 = GetUInt32ValueNullable(_UNIT_VIRTUAL_ITEM_SLOT_ID.Value);
            var _UNIT_VIRTUAL_ITEM_SLOT_ID_1 = GetUInt32ValueNullable(_UNIT_VIRTUAL_ITEM_SLOT_ID.Value + 1);
            var _UNIT_VIRTUAL_ITEM_SLOT_ID_2 = GetUInt32ValueNullable(_UNIT_VIRTUAL_ITEM_SLOT_ID.Value + 2);

            if (
                _UNIT_VIRTUAL_ITEM_SLOT_ID_0 != null ||
                _UNIT_VIRTUAL_ITEM_SLOT_ID_1 != null ||
                _UNIT_VIRTUAL_ITEM_SLOT_ID_2 != null
                )
            {
                if (_creature_equip_template == null)
                {
                    _creature_equip_template = new creature_equip_template();
                    _creature_equip_template.entry = ENTRY;
                }

                if (_creature_equip_template.equipentry1 == null && _UNIT_VIRTUAL_ITEM_SLOT_ID_0 != null)
                    _creature_equip_template.equipentry1 = _UNIT_VIRTUAL_ITEM_SLOT_ID_0;
                if (_creature_equip_template.equipentry2 == null && _UNIT_VIRTUAL_ITEM_SLOT_ID_1 != null)
                    _creature_equip_template.equipentry2 = _UNIT_VIRTUAL_ITEM_SLOT_ID_1;
                if (_creature_equip_template.equipentry3 == null && _UNIT_VIRTUAL_ITEM_SLOT_ID_2 != null)
                    _creature_equip_template.equipentry3 = _UNIT_VIRTUAL_ITEM_SLOT_ID_2;
            }
        }

        public void UpdateCreatureTemplateAddon()
        {
            var _UNIT_FIELD_BYTES_1 = GetUInt32ValueNullable(GetEnumByName("UNIT_FIELD_BYTES_1").GetValueOrDefault(-1));
            var _UNIT_FIELD_BYTES_2 = GetUInt32ValueNullable(GetEnumByName("UNIT_FIELD_BYTES_2").GetValueOrDefault(-1));
            var _UNIT_NPC_EMOTESTATE = GetUInt32ValueNullable(GetEnumByName("UNIT_NPC_EMOTESTATE").GetValueOrDefault(-1));
            var _UNIT_FIELD_MOUNTDISPLAYID = GetUInt32ValueNullable(GetEnumByName("UNIT_FIELD_MOUNTDISPLAYID").GetValueOrDefault(-1));
            var _UNIT_FIELD_AURASTATE = GetUInt32ValueNullable(GetEnumByName("UNIT_FIELD_AURASTATE").GetValueOrDefault(-1));

            if (_UNIT_FIELD_BYTES_1 != null &&
                _UNIT_FIELD_BYTES_2 != null)
            {
                if (_creature_template_addon == null)
                {
                    _creature_template_addon = new creature_template_addon();
                    _creature_template_addon.entry = ENTRY;
                }

                if (_creature_template_addon.mount == null && _UNIT_FIELD_MOUNTDISPLAYID != null)
                    _creature_template_addon.mount = _UNIT_FIELD_MOUNTDISPLAYID;

                if (_creature_template_addon.bytes1 == null && _UNIT_FIELD_BYTES_1 != null)
                    _creature_template_addon.bytes1 = _UNIT_FIELD_BYTES_1;

                if (_creature_template_addon.bytes2 == null && _UNIT_FIELD_BYTES_2 != null)
                    _creature_template_addon.bytes2 = _UNIT_FIELD_BYTES_2;

                if (_creature_template_addon.emote == null && _UNIT_NPC_EMOTESTATE != null)
                    _creature_template_addon.emote = _UNIT_NPC_EMOTESTATE;

                if (_creature_template_addon.moveflags == null && movementInfo.movementFlags != null)
                    _creature_template_addon.moveflags = (uint?)movementInfo.movementFlags;


                //tcreature_template_addon.auras;

            }
        }




        public bool HasTarget()
        {
            var _UNIT_FIELD_TARGET = (ulong?)GetUpdateValueNullable("UNIT_FIELD_TARGET", typeof(ulong));

            return (_UNIT_FIELD_TARGET != null && _UNIT_FIELD_TARGET.Value == 0);
        }

        public bool IsCreatedSummonedOrCharmedByPlayer()
        {
            //var _UNIT_FIELD_CHARM = (ulong?)GetUpdateValueNullable("UNIT_FIELD_CHARM", typeof(ulong));
            //var _UNIT_FIELD_SUMMON = (ulong?)GetUpdateValueNullable("UNIT_FIELD_SUMMON", typeof(ulong));
            //var _UNIT_FIELD_CRITTER = (ulong?)GetUpdateValueNullable("UNIT_FIELD_CRITTER", typeof(ulong));
            var _UNIT_FIELD_CHARMEDBY = (ulong?)GetUpdateValueNullable("UNIT_FIELD_CHARMEDBY", typeof(ulong));
            var _UNIT_FIELD_SUMMONEDBY = (ulong?)GetUpdateValueNullable("UNIT_FIELD_SUMMONEDBY", typeof(ulong));
            var _UNIT_FIELD_CREATEDBY = (ulong?)GetUpdateValueNullable("UNIT_FIELD_CREATEDBY", typeof(ulong));

            return (Sender.IsGuidPlayer(_UNIT_FIELD_CHARMEDBY) ||
                Sender.IsGuidPlayer(_UNIT_FIELD_SUMMONEDBY) ||
                Sender.IsGuidPlayer(_UNIT_FIELD_CREATEDBY));

        }

        public int? UNIT_FIELD_HEALTH
        {
            get
            {
                return (int?)GetUpdateValueNullable("UNIT_FIELD_HEALTH", typeof(int));
            }
        }

        public int? UNIT_FIELD_MAXHEALTH
        {
            get
            {
                return (int?)GetUpdateValueNullable("UNIT_FIELD_MAXHEALTH", typeof(int));
            }
        }

        public bool HasDamage()
        {
            var _UNIT_FIELD_HEALTH = UNIT_FIELD_HEALTH;
            var _UNIT_FIELD_MAXHEALTH = UNIT_FIELD_MAXHEALTH;

            if (_UNIT_FIELD_HEALTH != null && _UNIT_FIELD_MAXHEALTH != null && (_UNIT_FIELD_HEALTH != _UNIT_FIELD_MAXHEALTH))
            {
                var result = _UNIT_FIELD_MAXHEALTH.Value - _UNIT_FIELD_HEALTH.Value;
                return true;
            }

            return false;
        }

        public bool IsValidForUnitDataCapture()
        {
            return (TypeID == TypeID.TYPEID_UNIT && !HasTarget() && !IsCreatedSummonedOrCharmedByPlayer() && (UNIT_FIELD_HEALTH != null && UNIT_FIELD_MAXHEALTH != null) && !HasDamage());

        }

        public override void UpdateAuraInfo(DefinitionBase def)
        {
            if (IsValidForUnitDataCapture())
            {
                if (def is PACKETPARSERMAX20.CORE.DEFINITIONS.SMSG_AURA_UPDATE_DEF)
                {
                    var _def = (PACKETPARSERMAX20.CORE.DEFINITIONS.SMSG_AURA_UPDATE_DEF)def;

                    var list = _def.validauraupdatelist;

                    if (list.Count > 0)
                    {
                        if (_creature_template_addon == null)
                        {
                            _creature_template_addon = new creature_template_addon();
                            _creature_template_addon.entry = ENTRY;
                        }

                        foreach (var item in list)
                        {
                            if (GlobalCache.IsValidInitialAura(ENTRY, item.Value.id))
                            {
                                if (!AuraSpellIdList.Contains(item.Value.id))
                                {
                                    AuraSpellIdList.Add(item.Value.id);

                                    byte eff = GlobalCache.ValidAuraSpellIDEffectList[item.Value.id];

                                    for (int i = 0; i <= eff; i++)
                                    {
                                        if (_creature_template_addon.auras == null)
                                        {
                                            _creature_template_addon.auras = item.Value.id.ToString() + " " + i.ToString();
                                        }
                                        else
                                        {
                                            _creature_template_addon.auras += " " + item.Value.id.ToString() + " " + i.ToString(); ;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        public override void UpdateData(OBJECT_UPDATE_TYPE updatetype)
        {
            if (IsValidForUnitDataCapture())
            {
                UpdateCreatureEquipTemplate();
                UpdateCreatureTemplateAddon();
            }
        }
    }
}



//UNIT_FIELD_CHARM = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
//UNIT_FIELD_SUMMON = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
//UNIT_FIELD_CRITTER = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PRIVATE
//UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC
//UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC
//UNIT_FIELD_CREATEDBY = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC
//UNIT_FIELD_TARGET = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC
//UNIT_FIELD_CHANNEL_OBJECT = OBJECT_END + 0x000E, // Size: 2, Type: LONG, Flags: PUBLIC
//UNIT_FIELD_BYTES_0 = OBJECT_END + 0x0010, // Size: 1, Type: BYTES, Flags: PUBLIC
//UNIT_FIELD_HEALTH = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_POWER1 = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_POWER2 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_POWER3 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_POWER4 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_POWER5 = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_POWER6 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_POWER7 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001E, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_MAXPOWER6 = OBJECT_END + 0x001F, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_MAXPOWER7 = OBJECT_END + 0x0020, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER = OBJECT_END + 0x0021, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER_1 = OBJECT_END + 0x0022, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER_2 = OBJECT_END + 0x0023, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER_3 = OBJECT_END + 0x0024, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER_4 = OBJECT_END + 0x0025, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER_5 = OBJECT_END + 0x0026, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER_6 = OBJECT_END + 0x0027, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER = OBJECT_END + 0x0028, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER_1 = OBJECT_END + 0x0029, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER_2 = OBJECT_END + 0x002A, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER_3 = OBJECT_END + 0x002B, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER_4 = OBJECT_END + 0x002C, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER_5 = OBJECT_END + 0x002D, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER_6 = OBJECT_END + 0x002E, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_LEVEL = OBJECT_END + 0x002F, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x0030, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_VIRTUAL_ITEM_SLOT_ID = OBJECT_END + 0x0031, // Size: 3, Type: INT, Flags: PUBLIC
//UNIT_VIRTUAL_ITEM_SLOT_ID_1 = OBJECT_END + 0x0032, // Size: 3, Type: INT, Flags: PUBLIC
//UNIT_VIRTUAL_ITEM_SLOT_ID_2 = OBJECT_END + 0x0033, // Size: 3, Type: INT, Flags: PUBLIC
//UNIT_FIELD_FLAGS = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_AURASTATE = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x0037, // Size: 2, Type: INT, Flags: PUBLIC
//UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: PRIVATE
//UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x003A, // Size: 1, Type: FLOAT, Flags: PUBLIC
//UNIT_FIELD_COMBATREACH = OBJECT_END + 0x003B, // Size: 1, Type: FLOAT, Flags: PUBLIC
//UNIT_FIELD_DISPLAYID = OBJECT_END + 0x003C, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x003D, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x003E, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x003F, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
//UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0040, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
//UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0041, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
//UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0042, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
//UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0043, // Size: 1, Type: BYTES, Flags: PUBLIC
//UNIT_FIELD_PETNUMBER = OBJECT_END + 0x0044, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x0045, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x0046, // Size: 1, Type: INT, Flags: OWNER_ONLY
//UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x0047, // Size: 1, Type: INT, Flags: OWNER_ONLY
//UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x0048, // Size: 1, Type: INT, Flags: DYNAMIC
//UNIT_CHANNEL_SPELL = OBJECT_END + 0x0049, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_MOD_CAST_SPEED = OBJECT_END + 0x004A, // Size: 1, Type: FLOAT, Flags: PUBLIC
//UNIT_CREATED_BY_SPELL = OBJECT_END + 0x004B, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_NPC_FLAGS = OBJECT_END + 0x004C, // Size: 1, Type: INT, Flags: DYNAMIC
//UNIT_NPC_EMOTESTATE = OBJECT_END + 0x004D, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_STAT0 = OBJECT_END + 0x004E, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_STAT1 = OBJECT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_STAT2 = OBJECT_END + 0x0050, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_STAT3 = OBJECT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_STAT4 = OBJECT_END + 0x0052, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x0053, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x0055, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x0056, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x0057, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x0058, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x005A, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x005C, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCES = OBJECT_END + 0x005D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3
//UNIT_FIELD_RESISTANCES_1 = OBJECT_END + 0x005E, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3
//UNIT_FIELD_RESISTANCES_2 = OBJECT_END + 0x005F, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3
//UNIT_FIELD_RESISTANCES_3 = OBJECT_END + 0x0060, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3
//UNIT_FIELD_RESISTANCES_4 = OBJECT_END + 0x0061, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3
//UNIT_FIELD_RESISTANCES_5 = OBJECT_END + 0x0062, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3
//UNIT_FIELD_RESISTANCES_6 = OBJECT_END + 0x0063, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3
//UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x0064, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE_1 = OBJECT_END + 0x0065, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE_2 = OBJECT_END + 0x0066, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE_3 = OBJECT_END + 0x0067, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE_4 = OBJECT_END + 0x0068, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE_5 = OBJECT_END + 0x0069, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE_6 = OBJECT_END + 0x006A, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x006B, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE_1 = OBJECT_END + 0x006C, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE_2 = OBJECT_END + 0x006D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE_3 = OBJECT_END + 0x006E, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE_4 = OBJECT_END + 0x006F, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE_5 = OBJECT_END + 0x0070, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE_6 = OBJECT_END + 0x0071, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_BASE_MANA = OBJECT_END + 0x0072, // Size: 1, Type: INT, Flags: PUBLIC
//UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x0073, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_BYTES_2 = OBJECT_END + 0x0074, // Size: 1, Type: BYTES, Flags: PUBLIC
//UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x0075, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x0076, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x0077, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x0078, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x0079, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x007A, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x007B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x007C, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x007D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MODIFIER_1 = OBJECT_END + 0x007E, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MODIFIER_2 = OBJECT_END + 0x007F, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MODIFIER_3 = OBJECT_END + 0x0080, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MODIFIER_4 = OBJECT_END + 0x0081, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MODIFIER_5 = OBJECT_END + 0x0082, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MODIFIER_6 = OBJECT_END + 0x0083, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x0084, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MULTIPLIER_1 = OBJECT_END + 0x0085, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MULTIPLIER_2 = OBJECT_END + 0x0086, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MULTIPLIER_3 = OBJECT_END + 0x0087, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MULTIPLIER_4 = OBJECT_END + 0x0088, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MULTIPLIER_5 = OBJECT_END + 0x0089, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_POWER_COST_MULTIPLIER_6 = OBJECT_END + 0x008A, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x008B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
//UNIT_FIELD_HOVERHEIGHT = OBJECT_END + 0x008C, // Size: 1, Type: FLOAT, Flags: PUBLIC
//UNIT_FIELD_PADDING = OBJECT_END + 0x008D, // Size: 1, Type: INT, Flags: NONE
//UNIT_END = OBJECT_END + 0x008E,
